#include "akichannelstat.h"

//headers necessary for Qt 
#include <QLabel>
#include <QAction>
#include <QApplication>
#include <QClipboard>
#include <QGraphicsGridLayout>
#include <QGraphicsLinearLayout>
#include <QGraphicsProxyWidget>
#include <QFontMetrics>
#include <QSizePolicy>
#include <QPainter>
#include <QAbstractSocket>
#include <QGraphicsWidget>
#include <QMap>
#include <QListWidgetItem>
#include <QListWidget>
//headers necessary for Plasma Apletts 
#include <Plasma/Applet>
#include <Plasma/Theme>
#include <Plasma/PushButton>
#include <Plasma/Label>
#include <Plasma/Frame>
#include <Plasma/TreeView>
#include <Plasma/LineEdit>
#include <Plasma/TextEdit>
#include <KTextEdit>
#include <KDebug>
//headers necessary for aki
#include <Aki/Irc/Socket>
#include <Aki/Irc/User>

//Aki for the IRC part 
/** 
 * Dunno What you think of it but to me it looks a bit scatterd -.-
 * But yes this is in general how the aki API is build up.
 */
using namespace Aki;
using namespace Aki::Irc;

class Socket;

akichannelstat::akichannelstat(QObject *parent, const QVariantList &args)
  : Plasma::PopupApplet( parent, args ),
    m_widget(0),
    m_layout(0)
{
  setMinimumSize(50,50);
  resize(400, 200);
  setPopupIcon("aki");
}

akichannelstat::~akichannelstat()
{
    if (hasFailedToLaunch()) {
        // Do some cleanup here
    } else {
        // Save settings
    }
}

QGraphicsWidget *akichannelstat::graphicsWidget()
{
  if(!akichannelstat::m_widget)
    {
      akichannelstat::m_widget       = new QGraphicsWidget(this);
      akichannelstat::m_layout       = new QGraphicsLinearLayout(m_widget);
      akichannelstat::adressLayout   = new QGraphicsLinearLayout();
      akichannelstat::nickLayout     = new QGraphicsLinearLayout();
      akichannelstat::channelLayout  = new QGraphicsLinearLayout();
      
      akichannelstat::plasmoidTitle  = new Plasma::Label();
      akichannelstat::plasmoidTitle->setText("AkiIrc Connect Test\nbased on akiirc(0.0.2)");
      akichannelstat::plasmoidTitle->setAlignment(Qt::AlignHCenter);
      akichannelstat::m_layout->addItem(akichannelstat::plasmoidTitle);
      
      //adress label and edit-field
      akichannelstat::adressLabel = new Plasma::Label();
      akichannelstat::adressLabel->setText("Hostadress/Port:");
      akichannelstat::adressLabel->setAlignment(Qt::AlignHCenter);
      akichannelstat::adressLayout->addItem(akichannelstat::adressLabel);
      
      akichannelstat::adressEdit = new Plasma::LineEdit();
      akichannelstat::adressEdit->setText("irc.freenode.net/6667");
      akichannelstat::adressLayout->addItem(akichannelstat::adressEdit);
      akichannelstat::m_layout->addItem(akichannelstat::adressLayout);
      
      //nick label and edit-field
      akichannelstat::nickLabel = new Plasma::Label();
      akichannelstat::nickLabel->setText("Nickname");
      akichannelstat::nickLabel->setAlignment(Qt::AlignHCenter);
      akichannelstat::nickLayout->addItem(akichannelstat::nickLabel);
      
      akichannelstat::nickEdit = new Plasma::LineEdit();
      akichannelstat::nickEdit->setText("aki_test_user");
      akichannelstat::nickLayout->addItem(akichannelstat::nickEdit);
      akichannelstat::m_layout->addItem(akichannelstat::nickLayout);
					
      //channel label and edit-field
      akichannelstat::channelLabel = new Plasma::Label();
      akichannelstat::channelLabel->setText("Channelname");
      akichannelstat::channelLabel->setAlignment(Qt::AlignHCenter);
      akichannelstat::channelLayout->addItem(akichannelstat::channelLabel);
      
      akichannelstat::channelEdit = new Plasma::LineEdit();
      akichannelstat::channelEdit->setText("#freenode");
      akichannelstat::channelLayout->addItem(akichannelstat::channelEdit);
      akichannelstat::m_layout->addItem(akichannelstat::channelLayout);

      akichannelstat::startTest = new Plasma::PushButton();
      akichannelstat::startTest->setText("start Test.");
      akichannelstat::m_layout->addItem(akichannelstat::startTest);
      connect(akichannelstat::startTest,SIGNAL(clicked()),
	      this, SLOT(testClicked()));
      
      akichannelstat::ResultLog = new Plasma::TextEdit();
      akichannelstat::ResultLog->setText("no test yet.");
      akichannelstat::m_layout->addItem(akichannelstat::ResultLog);
      akichannelstat::m_layout->setOrientation(Qt::Vertical);
      akichannelstat::m_widget->setLayout(akichannelstat::m_layout);
      
    }
  return akichannelstat::m_widget;
}
/**
 * For working with aki this is the part that should interest you the most
 * It basically initiallizes a socket for 
 */

void akichannelstat::testClicked()
{
  
  akichannelstat::socket = new Aki::Irc::Socket();              
  
  //As this is a plasmoid and i didnt find anything else appropriate for this 
  //you might want to use some kind of list widget in your application
  //for the sake of this examble we stick with a cast.
  akichannelstat::socket->setAddressList((QStringList() << akichannelstat::adressEdit->text()));
  akichannelstat::socket->setChannelList((QStringList() << akichannelstat::nickEdit->text()));
  akichannelstat::socket->setNickList((QStringList() <<  akichannelstat::channelEdit->text()));
  
  //Some of these things may apply to you when you are a bigger application 
  //but we will just set these hard coded. 
  akichannelstat::socket->setAutoIdentify(false);    
  akichannelstat::socket->setAutoJoinChannels(true); 
  akichannelstat::socket->setAutoReconnection(false);

  akichannelstat::socket->setIdentity("AkiIrc Test Applet");
  akichannelstat::socket->setRealName("AkiIrc Test Applet");
  
  akichannelstat::socket->setRetryAttemptCount(3); //we try to connect 3 times
  akichannelstat::socket->setRetryInterval(10); // each ten seconds a new try to connect
  
  akichannelstat::socket->setSsl(false);
  QObject::connect( akichannelstat::socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
		    this, SLOT(connectStatus(QAbstractSocket::SocketState)));
  akichannelstat::socket->connectToHost(); //lets start connecting :-)
  
}

//This might be interesting for the nepomuk folks too as you can gather 
//information from the channel for examble the title of a channel or the 
//current comment can be parsed through the database. etc,

void akichannelstat::connectStatus(QAbstractSocket::SocketState state)
{
  
  //quoted verbatim from the Qt Documentation:
  /**********************************************************************************************
   ||         CONSTANT                 ||VAL||         DESCRIPTION                              
   ----------------------------------------------------------------------------------------------
   || QAbstractSocket::UnconnectedState|| 0 || The socket is not connected.
   || QAbstractSocket::HostLookupState || 1 || The socket is performing a host name lookup.
   || QAbstractSocket::ConnectingState || 2 || The socket has started establishing a connection.
   || QAbstractSocket::ConnectedState  || 3 || A connection is established.     
   || QAbstractSocket::BoundState      || 4 || The socket is bound to 
   ||                                  ||   || an address and port (for servers)
   || QAbstractSocket::ListeningState  || 5 || For internal use only.
   || QAbstractSocket::ClosingState    || 6 || The socket is about to close
   ||                                  ||   || (data may still be waiting to be written).
   ----------------------------------------------------------------------------------------------
  **********************************************************************************************/
  //We will simply log all information gathered.


  akichannelstat::time = new QTime;
  connect(this,SIGNAL(isUnconnected()),this,SLOT(unconnected()));
  connect(this,SIGNAL(isLookingUphost()),this,SLOT(lookingUpHost()));
  connect(this,SIGNAL(isConnecting()),this,SLOT(connecting()));
  connect(this,SIGNAL(isConnected()),this,SLOT(connected()));
  connect(this,SIGNAL(isBound()),this,SLOT(bound()));
  connect(this,SIGNAL(isInternal()),this,SLOT(internal()));
  connect(this,SIGNAL(isClosing()),this,SLOT(closing()));
  switch(state)
    {
    case 0:
      {
	emit akichannelstat::isUnconnected();
	break;
      }
    case 1:
      {
	emit akichannelstat::isLookingUphost();
	break;
      }
    case 2:
      {
	emit akichannelstat::isConnecting(); 
	break;
      }
    case 3:
      {
	emit akichannelstat::isConnected();
	break;
      }
    case 4:
      {
        emit akichannelstat::isBound();
	break;
      }
    case 5:
      {
	emit akichannelstat::isInternal();
	break;
      }
    case 6:
      {
        emit akichannelstat::isClosing();
	break;
      }
    }
}
	

void akichannelstat::unconnected()
{
  QString newLog = akichannelstat::ResultLog->text() +"(" 
    + akichannelstat::time->currentTime().toString("hh:mm:ss:zzz")
    + "): STATUS:The socket is not connected. \n";
  akichannelstat::ResultLog->setText(newLog);
}
void akichannelstat::lookingUpHost()
{
  QString newLog = akichannelstat::ResultLog->text() +"("
    + akichannelstat::time->currentTime().toString("hh:mm:ss:zzz")
    + "):STATUS:The socket is performing a host name lookup... \n";
  akichannelstat::ResultLog->setText(newLog);
}
void akichannelstat::connecting()
{
  QString newLog = akichannelstat::ResultLog->text() +"(" 
    + akichannelstat::time->currentTime().toString("hh:mm:ss:zzz")
    + "):STATUS:The socket has started establishing a connection. \n"
    + "\t Nick:" + akichannelstat::socket->currentNick() + "\n"
    + "\t Port:" + QString(akichannelstat::socket->currentPort()) + "\n";
akichannelstat::ResultLog->setText(newLog);
}
void akichannelstat::connected()
{
  QString newLog = akichannelstat::ResultLog->text() +"(" 
    + akichannelstat::time->currentTime().toString("hh:mm:ss:zzz")
    + "):STATUS:A connection is established.\n"
    + "\t Nick:" + akichannelstat::socket->currentNick() + "\n"
    + "\t Port:" + QString(akichannelstat::socket->currentPort()) + "\n";
akichannelstat::ResultLog->setText(newLog);
}
void akichannelstat::bound()
{
  QString newLog = akichannelstat::ResultLog->text() +"(" 
    + akichannelstat::time->currentTime().toString("hh:mm:ss:zzz")
    + "):STATUS:The socket is bound to an address and port (for servers). \n"
    + "\t Nick:" + akichannelstat::socket->currentNick() + "\n"
    + "\t Port:" + QString(akichannelstat::socket->currentPort()) + "\n";
  akichannelstat::ResultLog->setText(newLog);
}

void akichannelstat::internal()
{
  QString newLog = akichannelstat::ResultLog->text() + "(" 
    + akichannelstat::time->currentTime().toString("hh:mm:ss:zzz")
    + "):STATUS:For internal use only. \n"  
    + "\t Nick:" + akichannelstat::socket->currentNick() + "\n" 
    + "\t Port:" + QString(akichannelstat::socket->currentPort()) + "\n";
akichannelstat::ResultLog->setText(newLog);
}
void akichannelstat::closing()
{
  QString newLog = akichannelstat::ResultLog->text() + "("
    + akichannelstat::time->currentTime().toString("hh:mm:ss:zzz")
    + "):STATUS:The socket is about to close (data may still be waiting to be written). \n" 
    + "\t Nick:" + akichannelstat::socket->currentNick() + "\n" 
    + "\t Port:" + QString(akichannelstat::socket->currentPort()) + "\n";
akichannelstat::ResultLog->setText(newLog);
}

#include "akichannelstat.moc"
